import { ActivatedRoute } from '@angular/router';
import { ModalController, ToastController } from '@ionic/angular';
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';

import { Subject } from 'rxjs';
import { endsWith } from 'lodash';
import { EditorComponent } from 'ngx-monaco-editor';

import { pb } from 'src/pb';
import { LANGUAGES } from './language';
import { WsService } from '../services/ws.service';
import { FileService } from '../services/file.service';
import { SettingsPage } from './settings/settings.page';
import { DomSanitizer } from '@angular/platform-browser';
import { SettingsService } from '../services/settings.service';
@Component({
  selector: 'app-view',
  templateUrl: './view.page.html',
  styleUrls: ['./view.page.scss'],
})
export class ViewPage implements OnInit, OnDestroy {
  @ViewChild(EditorComponent, { static: true })
  editor: EditorComponent;
  file: pb.IFileInfo = {};
  text: pb.IText = { offset: 0 };
  private id: string;
  private write$ = new Subject<string>();
  constructor(
    private ss: SettingsService,
    private ws: WsService,
    private fs: FileService,
    private sanitizer: DomSanitizer,
    private toastCtrl: ToastController,
    private modalCtrl: ModalController,
    private activatedRoute: ActivatedRoute,
  ) {
    this.id = this.activatedRoute.snapshot.paramMap.get('id');
    this.ws.write$ = undefined;
  }

  get setting() {
    this.ss.settings.lineNumbers = (i) => i + this.text.offset;
    return this.ss.settings;
  }

  get showEditor() {
    return this.file.type === pb.FileType.code ||
      this.file.type === pb.FileType.text;
  }

  get showEmbed() {
    return this.file.type === pb.FileType.pdf ||
      this.file.type === pb.FileType.audio ||
      this.file.type === pb.FileType.video;
  }

  get url() {
    return this.sanitizer.bypassSecurityTrustResourceUrl(`/api/file/original/${this.id}`);
  }

  ngOnDestroy() {
    this.ws.close(this.file.id);
  }

  async ngOnInit() {
    this.file = await this.fs.file(this.id);
    if (this.file.type === pb.FileType.code ||
      this.file.type === pb.FileType.text) {
      this.ws.write$ = this.write$;
      this.write$.subscribe(id => {
        if (id === this.file.id) {
          this.getText();
          this.toast('文件修改');
        }
      });
      this.getText();
    }

    this.ws.open(this.file.id);

    for (const ls of LANGUAGES) {
      const exts = [ls.code];
      if (ls.ext) {
        exts.push(...ls.ext);
      }

      for (const l of exts) {
        if (endsWith(this.file.name, `.${l}`)) {
          this.ss.settings.language = ls.code;
          if (this.editor) {
            this.editor.options = this.ss.settings;
          }

          return;
        }
      }
    }
  }

  async settings() {
    const modal = await this.modalCtrl.create({
      component: SettingsPage,
      componentProps: { setting: Object.assign({}, this.ss.settings) },
    });
    await modal.present();

    const r = await modal.onDidDismiss();
    if (r.data) {
      // this.ss.settings.lineNumbers = (i) => i + this.text.offset;
      this.ss.settings = r.data;
      this.ss.settings.readOnly = true;

      if (this.editor) {
        this.editor.options = this.setting;
      }

      this.ss.save();
      if (this.ss.settings.autoRefresh) {
        this.ws.open(this.file.id);
      }
    }
  }

  async next() {
    this.text = await this.fs.text(this.id, (this.text.offset as number), 'next');
    if (this.editor) {
      this.editor.options = this.setting;
    }
  }

  async prev() {
    this.text = await this.fs.text(this.id, (this.text.offset as number), 'prev');
    if (this.editor) {
      this.editor.options = this.setting;
    }
  }

  private async getText() {
    this.text = await this.fs.text(this.id);
  }

  private async toast(msg: string) {
    const toast = await this.toastCtrl.create({
      message: msg,
      position: 'top',
      duration: 1000,
    });
    await toast.present();
  }
}
